<script>
import { onMounted, ref } from "vue";
import * as THREE from "three";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
export default {
  setup() {
    let scene, camera, renderer;
    let mixer, cameraMixer;
    let controls;
    let clock = new THREE.Clock();
    //相机位置
    const cameraX = 0;
    const cameraY = 3;
    const cameraZ = 6;
    const bgColor = new THREE.Color("#f6f8f9");
    const canvasWrapper = ref();

    //初始化渲染器
    const initRenderer = () => {
      renderer = new THREE.WebGLRenderer({
        antialias: true,
      });
      renderer.setSize(
        canvasWrapper.value.clientWidth,
        canvasWrapper.value.clientHeight
      );
      renderer.shadowMap.enabled = true;
      canvasWrapper.value.appendChild(renderer.domElement);
    };

    //初始化场景
    const initScence = () => {
      scene = new THREE.Scene();
      scene.background = new THREE.Color(bgColor);
      scene.fog = new THREE.Fog(0xe0e0e0, 20, 100); //定义每个物体的雾的类型
    };

    //初始化灯光
    const initLight = () => {
      scene.add(new THREE.AmbientLight(0xffffff, 0.5));
      const arr = [
        [100, 100, 100],
        [-100, 100, 100],
        [100, -100, 100],
      ];
      arr.forEach((lightArr) => {
        let directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
        let [x, y, z] = lightArr;
        directionalLight.position.set(x, y, z);
        scene.add(directionalLight);
      });
    };

    //初始化物体
    const initMeshes = () => {
      //引入gltf模型
      const loader = new GLTFLoader();
      loader.load(
        "3d-model/login-show/RobotExpressive.glb",
        (gltf) => {
          const model = gltf.scene;
          scene.add(model);

          model.position.y = -2.5;
          model.rotation.x = -Math.PI / 12;
          model.rotation.y = Math.PI / 12;

          //添加阴影
          model.traverse((object) => {
            if (object.isMesh) object.castShadow = true;
          });

          //创建动画
          createGUI(model, gltf.animations);
        },
        (xhr) => {
          console.log(
            "加载完成的百分比" + (xhr.loaded / xhr.total) * 100 + "%"
          );
        }
      );
    };

    //创建动画
    const createGUI = (model, animations) => {
      const animationClip = animations.find(
        (animationClip) => animationClip.name === "Dance"
      );
      mixer = new THREE.AnimationMixer(model);
      const action = mixer.clipAction(animationClip);
      action.play();
    };

    //初始化相机
    const initCamera = () => {
      camera = new THREE.PerspectiveCamera(
        45,
        canvasWrapper.value.clientWidth / canvasWrapper.value.clientHeight,
        0.1,
        100000
      );
      camera.position.set(cameraX, cameraY, cameraZ);
    };

    //初始化控制器
    const initControls = () => {
      controls = new OrbitControls(camera, renderer.domElement);
      controls.maxDistance = 20; //设置缩放范围
      controls.maxPolarAngle = Math.PI / 1.2; //设置旋转范围
    };

    //渲染场景
    const animate = () => {
      requestAnimationFrame(animate);
      renderer.render(scene, camera);
      const delta = clock.getDelta();
      if (mixer) mixer.update(delta);
      if (cameraMixer) cameraMixer.update(delta);
    };

    //防抖
    const debounce = (func, wait) => {
      let timeout;
      return function () {
        const context = this;
        const args = arguments;
        if (timeout) clearTimeout(timeout);
        timeout = setTimeout(() => {
          func.apply(context, args);
        }, wait);
      };
    };

    const resizeHandler = () => {
      // 重置渲染器输出画布canvas尺寸
      renderer.setSize(
        canvasWrapper.value.clientWidth,
        canvasWrapper.value.clientHeight
      );
      camera.aspect =
        canvasWrapper.value.clientWidth / canvasWrapper.value.clientHeight;
      camera.updateProjectionMatrix();
    };

    const cancalDebounce = debounce(resizeHandler, 500);

    window.addEventListener("resize", cancalDebounce);

    onMounted(() => {
      initRenderer();
      initScence();
      initLight();
      initMeshes();
      initCamera();
      initControls();
      animate();
    });

    return { canvasWrapper };
  },
};
</script>

<template>
  <div ref="canvasWrapper" style="width: 100%; height: 100%"></div>
</template>

<style scoped>
</style>